/**
 * Clase modificada de EventDispatcher de Macromedia
 * @author      JoH
 * @version     20071210
 */
//****************************************************************************
//Copyright (C) 2003 Macromedia, Inc. All Rights Reserved.
//The following is Sample Code and is subject to all restrictions on
//such code as contained in the End User License Agreement accompanying
//this product.
//****************************************************************************

/**
* base class for event listening and dispatching
*
* @helpid 3295
* @tiptext
*/
class com.dmotiko.lib.EventDispatcherPro
{
        // make a instance of ourself so we can add methods to other objects
        static var _fEventDispatcher:EventDispatcherPro = undefined;

        // these events do not get called via backdoor because of name collisions with other methods
        static var exceptions:Object = {move: 1, draw: 1, load:1};
        /**
        * object with all listeners
        */
        static var _queues:Object;
        static var _queuesCount:Number;
        // internal function for removing listeners
        static function _removeEventListener(queue:Object, event:String, handler):Void
        {
                if (queue != undefined)
                {
                        var l:Number = queue.length;
                        var i:Number;
                        for (i = 0; i < l; i++)
                        {
                                var o = queue[i].handler;
                                if (o == handler) {
                                        queue.splice(i, 1);
                                        return;
                                }
                        }
                }
        }

/**
* add listening and dispatching methods to an object
* @param object the object to receive the methods
*/
        static function initialize(object:Object):Void
        {
                if (_fEventDispatcher == undefined)
                {
                        _fEventDispatcher = new EventDispatcherPro;
                        EventDispatcherPro._queues = new Object();
                        EventDispatcherPro._queuesCount = 0;
                }
                object.addEventListener = _fEventDispatcher.addEventListener;
                object.removeEventListener = _fEventDispatcher.removeEventListener;
                object.dispatchEvent = _fEventDispatcher.dispatchEvent;
                object.dispatchQueue = _fEventDispatcher.dispatchQueue;
                //---
                object["__qc_"] = EventDispatcherPro._queuesCount;
                EventDispatcherPro._queuesCount++;
        }

        // internal function for dispatching events
        function dispatchQueue(queueObj:Object, eventObj:Object, deleteListener:Boolean):Void
        {
                var queueName:String = "__q_" + eventObj.type;
                var queue:Array = queueObj[queueName];
                if (queue != undefined)
                {
                        var i:String;
                        // loop it as an object so it resists people removing listeners during dispatching
                        for (i in queue)
                        {
                                var o = queue[i].handler;
                                var oType:String = typeof(o);

                                // a handler can be a function, object, or movieclip
                                if (oType == "object" || oType == "movieclip")
                                {
                                        // this is a backdoor implementation that
                                        // is not compliant with the standard
                                        if (o.handleEvent != undefined)
                                        {
                                                // this is the DOM3 way
                                                o.handleEvent(eventObj);
                                        }
                                        if (o[eventObj.type] != undefined)
                                        {
                                                if (EventDispatcherPro.exceptions[eventObj.type] == undefined)
                                                {       
                                                        // this is a backdoor implementation that
                                                        // is not compliant with the standard
                                                        o[eventObj.type](eventObj);
                                                }
                                        }
                                }
                                else // it is a function
                                {
                                        o.apply(queueObj, [eventObj]);
                                }
                                //---
                                if (deleteListener) 
                                {
                                        EventDispatcherPro._removeEventListener(queueObj[queueName], eventObj.type, o);
                                }
                        }
                }
        }

/**
* dispatch the event to all listeners
* @param eventObj an Event or one of its subclasses describing the event
*/
        function dispatchEvent(eventObj:Object, deleteListener:Boolean):Void
        {
                if (eventObj.target == undefined)
                        eventObj.target = this;

                this[eventObj.type + "Handler"](eventObj);

                // Dispatch to objects that are registered as listeners for
                // this object.
                this.dispatchQueue(this, eventObj, deleteListener);
        }

/**
* add a listener for a particular event
* @param event the name of the event ("click", "change", etc)
* @param the function or object that should be called
*/
        function addEventListener(event:String, handler, tagName:String):Void
        {
                var queueName:String = "__q_" + event;
                var oQueue:Object = new Object();
                if (this[queueName] == undefined)
                {
                        this[queueName] = new Array();
                }
                if (EventDispatcherPro._queues[queueName] == undefined)
                {
                        EventDispatcherPro._queues[queueName] = new Object();
                }
                _global.ASSetPropFlags(this, queueName,1);

                EventDispatcherPro._removeEventListener(this[queueName], event, handler);
                //---
                oQueue.tagName = tagName;
                oQueue.handler = handler;
                //---
                this[queueName].push(oQueue);
                EventDispatcherPro._queues[queueName][this["__qc_"]] = this[queueName];
        }

/**
* remove a listener for a particular event
* @param event the name of the event ("click", "change", etc)
* @param the function or object that should be called
*/
        function removeEventListener(event:String, handler):Void
        {
                var queueName:String = "__q_" + event;
                EventDispatcherPro._removeEventListener(this[queueName], event, handler);
        }
        
/**
 * Elimina todos las escuchas que tengan ese tag
 * @param       tagname Tag a eliminar
 */
        public static function removeEventListenersForTagName(tagName:String):Void
        {
                if (tagName != undefined)
                {
                        var i:String;
                        var j:String;
                        var k:String;
                        var queues:Object;
                        var queue:Object;
                        //---
                        for (i in EventDispatcherPro._queues)
                        {
                                queues = EventDispatcherPro._queues[i];
                                //---
                                for (j in  queues) 
                                {
                                        queue = queues[j];
                                        //---
                                        for (k in queue)
                                        {
                                                var o = queue[k].tagName;
                                                if (o == tagName)
                                                {
                                                        queue.splice(k, 1);
                                                }
                                        }
                                }
                        }
                }
        }
        
/**
 * Remueve todas las escuchas que tengan ese nombre de evento
 * @param       event Nombre del evento a eliminar
 */
        public static function removeEventListenersForEvent(event:String):Void
        {
                if (event != undefined)
                {
                        var j:String;
                        var k:String;
                        var queues:Object;
                        var queue:Object;
                        //---
                        queues = EventDispatcherPro._queues["__q_" + event];
                        //---
                        for (j in  queues) 
                        {
                                queue = queues[j];
                                //---
                                for (k in queue)
                                {
                                        queue.splice(k, 1);
                                }
                        }
                        //---
                        delete EventDispatcherPro._queues["__q_" + event];
                }
        }
        
/**
 * Remueve todas las escuchas de la Clase / Objeto
 * @param       scope Ruta de la Clase / Objeto a eliminar
 */
        public static function removeEventListenersForScope(scope):Void
        {
                if (scope != undefined)
                {
                        if (scope["__qc_"] != undefined)
                        {
                                var scopeNumber:Number = scope["__qc_"];
                                var i:String;
                                var j:String;
                                var k:String;
                                var queues:Object;
                                var queue:Object;
                                //---
                                for (i in EventDispatcherPro._queues)
                                {
                                        queues = EventDispatcherPro._queues[i];
                                        //---
                                        for (j in  queues) 
                                        {
                                                if (j == scope["__qc_"])
                                                {
                                                        queue = queues[j];
                                                        //---
                                                        for (k in queue)
                                                        {
                                                                queue.splice(k, 1);
                                                        }
                                                        //---
                                                        delete EventDispatcherPro._queues[i][j];
                                                        //---
                                                        break;
                                                }
                                        }
                                }
                        }
                }
        }
        
/**
 * Remueve todas las escuchas que fueron registradas por esta clase
 */
        public static function removeAllEventListeners():Void
        {
                var i:String;
                var j:String;
                var k:String;
                var queues:Object;
                var queue:Object;
                //---
                for (i in EventDispatcherPro._queues)
                {
                        queues = EventDispatcherPro._queues[i];
                        //---
                        for (j in  queues) 
                        {
                                queue = queues[j];
                                //---
                                for (k in queue)
                                {
                                        queue.splice(k, 1);
                                }
                        }
                }
                //---
                EventDispatcherPro._queues = new Object();
        }
}